package ua.org.enginer.managers {
	
	import flash.events.EventDispatcher;
	
	import mx.collections.ArrayCollection;
	import mx.managers.CursorManager;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.remoting.RemoteObject;
	
	[Event(name="result", type="mx.rpc.events.ResultEvent")]
	
	public class AMFServiceManager	extends EventDispatcher {
		
		public var useDomainLogic:Boolean// = true
		public var useBusyCursor:Boolean = true
		private var service:RemoteObject
		
		/**
		 * Без services-config.xml работатает в режиме очереди... т.е. для логина мне нужно ждать
		 * пока загрузиться всё... не катит )
		 */ 
		function AMFServiceManager(domain:String, source:String = "PanCRM", secure:Boolean=false) {
			super()
			
			//var domain:String
			//var protocol:String
			
			// С раными протоколами не работает...
			//protocol = Registry.DEBUG_MODE ? "http" : "https"
			
			//protocol = Application.application.url.match(/[^\:]*/)[1]
			//domain = Application.application.url.match(/:\/\/(.*?)\//)[1]
			
			// todo: to IRegistry
			//if (Registry.DEBUG_MODE) {
			//	domain = "local"
			//}else {
			//	domain = Application.application.url.match(/:\/\/(.*?)\//)[1]
			//}
			//Security.loadPolicyFile("http://crm.pantele.com.ua/crossdomain.xml")
			//Security.allowDomain("crm.pantele.com.ua")
			//domain = "crm.pantele.com.ua"
			//var url:String = protocol+"://"+domain+"/amfphp/gateway.php"
			
			//var chan:Channel = protocol == "https" ? new SecureAMFChannel(null, url) : new AMFChannel(null, url)
			
			service = new RemoteObject(domain+(secure ? "-secure" : ""))
			/*service.channelSet = new ChannelSet();
            service.channelSet.addChannel(chan);*/
			service.source = source
		}
		
		public function insert(entity:String, data:Object, resultHandler:Function=null):void {
			this.resultHandler = resultHandler
			
			service.addEventListener(ResultEvent.RESULT, onInsertResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			
			service.insert(entity, data)
		}
		
		public function update(entity:String, data:Object, resultHandler:Function=null):void {
			this.resultHandler = resultHandler
			
			service.addEventListener(ResultEvent.RESULT, onUpdateResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			
			service.update(entity, data)
		}
		/*
		public function remove(entity:String, data:Object):void {
			service = new DeleteServise(entity)
			service.addEventListener(ResultEvent.RESULT, onResult)
			if (useBusyCursor) CursorManager.setBusyCursor()
			service.send(data)
		}
		*/
		private var result:ArrayCollection
		private var resultClass:Class
		private var owner:Object
		private var errorAnswer:String
		
		public function select(table:String, resultClass:Class=null, 
								query:String='', resultHandler:Function=null,
								owner:Object=null):ArrayCollection {
			
			this.resultClass = resultClass
			this.resultHandler = resultHandler
			this.owner = owner
			
			result = new ArrayCollection()
			
			service.addEventListener(ResultEvent.RESULT, onSelectResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			
			service.select(table, query, useDomainLogic)
			
			return result
		}
		
		public var resultHandler:Function
		/*
		public function selectFromBilling(query:String, resultClass:Class=null, resultHandler:Function=null):* {
			if(resultHandler) this.resultHandler = resultHandler
			 
			service = new BillingQueryServise()
			
			if (resultClass) BillingQueryServise(service).resultClass = resultClass
			
			service.addEventListener(ResultEvent.RESULT, onResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			service.send({query: query})
			
			return BillingQueryServise(service).result
		}
		
		public function execOnBilling(query:String):AsyncToken {
			service = new BillingQueryServise()
			
			service.addEventListener(ResultEvent.RESULT, onResult)
			service.addEventListener(FaultEvent.FAULT, onFault)
			
			if (useBusyCursor) CursorManager.setBusyCursor()
			
			return service.send({query: query})
		}

		/**
		 * Mail($_POST['email'], $_POST['subject'], $_POST['body'].$signature, 
		 *		$_POST['from'], $_POST['from_email'], $_POST['to']);
		 * / 
		public function mail(data:Object):void {
			service = new MailServise()
			service.addEventListener(ResultEvent.RESULT, onResult)
			service.send(data)
		}
		
		*/
		protected function onSelectResult(event:ResultEvent):void {
			if (useBusyCursor) CursorManager.removeBusyCursor()
			
			event.target.removeEventListener(ResultEvent.RESULT, onSelectResult)
			
			var item:Object
			for each (var o:Object in event.result) {
				if (resultClass) {
					item = new resultClass(o)
					//item.owner = owner ? owner : result
				}else 
					item = o
					
				item.owner = owner ? owner : result
				result.addItem(item)
			}
			
			if (resultHandler) {
				resultHandler.apply(this, [result])
				resultHandler = null
			}
			
			dispatchEvent(new ResultEvent("result", false, true, result))
		}
		
		protected function onUpdateResult(event:ResultEvent):void {
			if (useBusyCursor) CursorManager.removeBusyCursor()
			
			event.target.removeEventListener(ResultEvent.RESULT, onUpdateResult)
			
			errorAnswer = String(event.result)
			
			if (resultHandler) {
				resultHandler.apply(this, [])
				resultHandler = null
			}
		}
		
		protected function onInsertResult(event:ResultEvent):void {
			if (useBusyCursor) CursorManager.removeBusyCursor()
			
			event.target.removeEventListener(ResultEvent.RESULT, onInsertResult)
			
			if (resultHandler) {
				resultHandler.apply(this, [event.result])
				resultHandler = null
			}
		}
		
		
		protected function onFault(event:FaultEvent):void {
			event.target.removeEventListener(FaultEvent.FAULT, onFault)
			if (useBusyCursor) CursorManager.removeBusyCursor()
			trace(event.fault.faultDetail)
			//dispatchEvent(new ResultEvent("result", false, true, event.target.result))
		}
	}
}